package com.lj.sys.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lj.common.utils.CheckUtils;
import com.lj.mp.standard.StandardServiceImpl;
import com.lj.sys.constant.SysConstant;
import com.lj.sys.entity.SysDept;
import com.lj.sys.entity.SysUser;
import com.lj.sys.mapper.SysDeptMapper;
import com.lj.sys.param.SysDeptSaveParam;
import com.lj.sys.param.SysDeptUpdateParam;
import com.lj.sys.result.SysDeptInfoResult;
import com.lj.sys.service.SysDeptService;
import com.lj.sys.service.SysUserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统部门表 服务实现类
 * </p>
 *
 * @author luojing
 * @since 2024-12-20 21:27:32
 */
@Service
public class SysDeptServiceImpl extends StandardServiceImpl<SysDeptMapper, SysDept> implements SysDeptService, InitializingBean {

    /**
     * 系统部门树
     */
    private List<SysDeptInfoResult> sysDeptTreeList;

    /**
     * 系统部门 key: 部门id value：部门信息
     */
    private Map<Long, SysDeptInfoResult> sysDeptListMap;

    @Resource
    private SysUserService sysUserService;

    /**
     * 刷新部门树
     * 当删除，新增，更新时刷新部门树，当然这个操作不是频繁的(而且有很多部门吗？)
     * 所以不用担心
     */
    private synchronized void refreshSysDept() {
        List<SysDept> deptList = list();
        if (CollUtil.isEmpty(deptList)) {
            sysDeptTreeList = Collections.emptyList();
            sysDeptListMap = Collections.emptyMap();
        }
        sysDeptTreeList = deptList.stream().map(SysDeptInfoResult::of).collect(Collectors.toList());
        sysDeptListMap = sysDeptTreeList.stream().collect(Collectors.toMap(SysDeptInfoResult::getId, Function.identity()));
        // 组装树
        Iterator<SysDeptInfoResult> iterator = sysDeptTreeList.iterator();
        while (iterator.hasNext()) {
            SysDeptInfoResult next = iterator.next();
            // 这是在找父节点，将当前节点放到父节点的children中，并在resultList中删除
            SysDeptInfoResult parent = sysDeptListMap.get(next.getParentId());
            if (ObjectUtil.isNotNull(parent)) {
                parent.getChildren().add(next);
                iterator.remove();
            }
        }
    }

    @Override
    public List<SysDeptInfoResult> tree() {
        Long userId = StpUtil.getLoginIdAsLong();
        if (SysConstant.SUPER_ADMIN_ID.equals(userId)) {
            // 超级管理员可以管理所有部门
            return sysDeptTreeList;
        }
        // 普通用户，并且有管理部门的权限，那么只能管理自己本部门
        SysUser user = sysUserService.getById(userId);
        SysDeptInfoResult sysDeptInfoResult = sysDeptListMap.get(user.getDeptId());
        CheckUtils.ifNull(sysDeptInfoResult, "你不属于任何部门? 请联系管理员！");
        return Collections.singletonList(sysDeptInfoResult);
    }

    @Override
    public SysDeptInfoResult info(Long id) {
        return sysDeptListMap.get(id);
    }

    @Override
    public List<Long> allDeptId() {
        List<Long> result = new ArrayList<>();
        List<SysDeptInfoResult> deptInfoResults = tree();
        for (SysDeptInfoResult deptInfoResult : deptInfoResults) {
            List<SysDeptInfoResult> flattedDeptInfo = flatSysDeptInfo(deptInfoResult);
            result.addAll(flattedDeptInfo.stream().map(SysDeptInfoResult::getId).toList());
        }
        return result;
    }

    @Override
    public void save(SysDeptSaveParam param) {
        SysDept entity = param.toEntity();
        this.save(entity);
        refreshSysDept();
    }

    @Override
    public void update(SysDeptUpdateParam param) {
        SysDept entity = param.toEntity();
        this.updateById(entity);
        refreshSysDept();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        refreshSysDept();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        // 判断要删除的部门id列表
        SysDeptInfoResult sysDeptInfoResult = sysDeptListMap.get(id);
        CheckUtils.ifNull(sysDeptInfoResult, "未查询到部门！");
        List<SysDeptInfoResult> sysDeptInfoResultList = flatSysDeptInfo(sysDeptInfoResult);
        List<Long> deleteIds = sysDeptInfoResultList.stream().map(SysDeptInfoResult::getId).toList();
        // 先判断当前部门下已经没有用户了
        List<SysUser> sysUserList = sysUserService.getSysUserByDeptId(deleteIds);
        CheckUtils.ifNotEmpty(sysUserList, "该部门下还有用户，请先移除这些用户!");
        // 删除部门
        this.removeBatchByIds(deleteIds);
        refreshSysDept();
    }

    private List<SysDeptInfoResult> flatSysDeptInfo(SysDeptInfoResult sysDeptInfoResult) {
        List<SysDeptInfoResult> result = new ArrayList<>();
        result.add(sysDeptInfoResult);
        List<SysDeptInfoResult> children = sysDeptInfoResult.getChildren();
        if (CollUtil.isNotEmpty(children)) {
            for (SysDeptInfoResult child : children) {
                result.addAll(flatSysDeptInfo(child));
            }
        }
        return result;
    }
}
